package com.bjy.qa.util.security;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.ObjectPostProcessor;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.web.access.intercept.FilterSecurityInterceptor;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

import javax.annotation.Resource;

/**
 * SpringSecurity 配置
 */
@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true) // 开启方法级别的权限认证，后续不需要，要删除
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    @Resource
    private JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter; // JWT 过滤器

    @Resource
    AuthenticationEntryPointImpl autoetaticaticcAutryPointImpl; // 认证 时的异常（当用户请求一个受保护的资源，又没登录时触发）
    @Resource
    AccessDeniedPointImpl accessDeniedPointImpl; // 用户访问无权限资源 时的异常（用户登录后，请求一个受保护的资源，又没权限时触发）

    @Resource
    CustomFilterInvocationSecurityMetadataSource appFilterInvocationSecurityMetadataSource;
    @Resource
    CustomAccessDecisionManager customerAccessDecisionManger;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .csrf().disable() // 关闭跨站请求防护
                .cors().and() // 配置 CORS支持
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS); // 不通过 session 获取 SecurityContext

        // 配置自定义的权限验证类
        http
                .authorizeRequests().anyRequest().authenticated().withObjectPostProcessor(new ObjectPostProcessor<FilterSecurityInterceptor>() {
                    @Override
                    public <O extends FilterSecurityInterceptor> O postProcess(O o) {
                        o.setSecurityMetadataSource(appFilterInvocationSecurityMetadataSource); // 自定义请求 URL 与配置属性之间的映射类（根据请求的 URL，查找适用于该 URL 的权限配置属性，比如角色,权限等信息）
                        o.setAccessDecisionManager(customerAccessDecisionManger); // 自定义密名账户验证类，它负责根据 Authentication 对象、访问主体的权限信息以及资源的安全配置，决定主体是否有权限访问资源
                        return o;
                    }
                });

        // 配置异常处理器
        http
                .exceptionHandling()
                .authenticationEntryPoint(autoetaticaticcAutryPointImpl) // 认证 时的异常（当用户请求一个受保护的资源，又没登录时触发）
                .accessDeniedHandler(accessDeniedPointImpl); // 用户访问无权限资源 时的异常（用户登录后，请求一个受保护的资源，又没权限时触发）

        // 添加 JWT 过滤器
        http
                .addFilterBefore(jwtAuthenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);
    }

    @Bean
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }
}
